var UCD = UCD || {
    Core: jQuery
};
(function(ucd, $) { // "use strict";
    var TIMERS = new UCD.TimerManager();

    var utils = {
        toRad: function(angle) {
            return angle * Math.PI / 180;
        }
    };

    /**
     * @typedef {Object} DashBoardChartData
     * @property {Number} value                   进度值
     * @property {String} [color = '#66CC52']     圆环颜色
     */
    
    /**
     * 仪表盘
     *
     * 1. 支持设置刻度值、刻度个数;
     * 2. 支持设置告警值;
     * 3. 支持整体自适应缩放;
     * 4. 支持gray/black两种风格的
     * 5. 支持仪表盘事件回调:hover、click;
     *
     * @smartueExample 基本用法 charts/dashboard/basic.html
     * @smartueExample 显示刻度 charts/dashboard/show_rule.html
     * 
     * @class DashBoard
     * @memberOf UCD
     * 
     * @param {String|Object} container - jQuery selector
     */    
    ucd.DashBoard = function(container) {
        this._settings = {
            container: $(container),
            root: $("<div class='UCDChart Circle'></div>"),
            infoLayer: $("<div class='infoLayer'></div>"),
            strokeWidth: 30, //圆环大小
            r: 80, //半径
            minR: 20, //最小圆环半径
            maxR: 500, //最大圆环半径
            ruleNum: 10, //刻度个数
            fontSizeRatio: 0.3, //圆环里文本大小与r的比例
            animateTime: 1000, //动画执行时间
            centerText: {
                color: ucd.getStyle() == "gray" ? "#666766" : "#CCCCCC",
                fontFamily: "微软雅黑"
            }, //圆环中心内容样式
            baseColor: ucd.getStyle() == "gray" ? "#E2E2E2" : "#333333", //底圈颜色
            selectColor: "#0088cc", //选中颜色效果
            defaultColor: "#66CC52", //默认颜色
            ruleMaxVal: 10, //刻度默认最大值
            isShowAlarm: true, //是否显示告警dot
            alarmColors: null, // 默认使用getColor的getAlarmColors接口实现

            getAlarmColors: function() {
                if (!this._alarmColors) {
                    this._alarmColors = this.alarmColors || ucd.getAlarmColors([4, 3, 2, 1]);
                }
                return this._alarmColors;
            },

            sweepAngle: 180, 

            alarmCircleGap: 7, 

            bgStrokeColor: 'none', 
            bgStrokeWidth: 0, 
            bgStrokeLineJoin: 'miter',

            itemStrokeColor: 'none', 
            itemStrokeWidth: 0, 
            itemStrokeLineJoin: 'miter',

            rotate: 180 //初始角度
        };
        var settings = this._settings;
        settings.self = this;
        settings.root.addClass(ucd.getStyle()); //设置风格
        settings.frags = $("<div class='Frags'></div>").css({
            "overflow": "visible"
        });
        settings.cord = new ucd.Cords(settings.root);
        settings.Source = settings.cord._settings.Source;
        _infoLayer(settings, "no data loaded.");
        settings.textLine = []; //存储文本内容

        settings.container.empty().append(settings.root);
        settings.root.append(settings.infoLayer, settings.frags);
        if (settings.cord.isSVG()) {
            settings.svg = settings.cord.createElement("svg", {
                version: "1.1"
            }, settings.frags[0]);
        } else {
            settings.svg = $("<div></div>").css("position", "absolute").appendTo(settings.frags)[0];
        }
        settings.gDashBoard = settings.cord.createElement("g", null, settings.svg);
    }

    function _infoLayer(settings, tip) {
        settings.infoLayer.show();
        settings.infoLayer.html(tip);
    }

    function _setFragsSize(settings) {
        //如果环形显示图例
        var top = (settings.container.height() - settings.r) / 2 < 0 ? 10 : (settings.container.height() - settings.r) / 2;
        var left = (settings.container.width() - settings.r * 2) / 2
        settings.frags.css({
            "left": left,
            "top": top,
            "bottom": 0,
            "right": 0
        });

        settings.width = settings.r * 2;
        settings.height = settings.r;
        var ieH = 0; //兼容IE bug处理滚动条问题
        settings.addArea = 0;
        settings.cord.setAttributes(settings.svg, {
            "width": settings.width + settings.addArea,
            "height": settings.height - ieH + settings.addArea
        })
        settings.cord._settings.root.css({
            "z-index": 3,
            "position": "relative",
            "height": "auto",
            "overflow": "visible"
        });
    }

    function _setData(settings, type) {
            settings.angles = [];
            settings.center = [];

            _setR(settings);
            _setFragsSize(settings);
            _savePath(settings, type);
            _createRule(settings, type);
            if (settings.alarmData && settings.isShowAlarm) {
                _createAlarm(settings, type);
            }
        }
        //创建刻度
    function _createRule(settings, type) {
        if (type == "create") {
            settings.gRule = settings.cord.createElement("g", null, settings.svg);
            settings.textRule = $("<div></div>").appendTo(settings.frags);
        } else {
            $(settings.gRule).empty();
            settings.textRule.empty();
        }

        var num = settings.ruleMaxVal / settings.ruleNum;
        var sweepRad = utils.toRad(settings.sweepAngle);

        for (var i = 0; i <= settings.ruleNum; i++) {
            var items = {};
            var align = (i * num) / settings.ruleMaxVal;
            var tempLine = settings.angles[0] + sweepRad * align; //算出在2pi中所占的比例
            var lineItem = _getLinePath(settings, tempLine, settings.r + settings.bgStrokeWidth / 2, settings.center);
            var flag = false;
            $(settings.ruleData).each(function(index, element) {
                if (i * num == settings.ruleData[index]) {
                    var textStr = $("<span></span>").text(i * num).css({
                        "position": "absolute",
                        "color": "#999999"
                    }).appendTo(settings.textRule);
                    var x = i * num < settings.ruleMaxVal / 2 ? lineItem.startX - textStr.width() : lineItem.startX;
                    var x = i * num == settings.ruleMaxVal / 2 ? lineItem.startX - textStr.width() / 2 : x;
                    var y = lineItem.startY;
                    textStr.css({
                        "left": x,
                        "top": y - textStr.height() + 4
                    });
                    flag = true;
                }
            });
            if (!flag && settings.isRule) {
                settings.cord.createElement("path", {
                    "d": lineItem.path,
                    "fill": "none",
                    "stroke": "#999999",
                    "stroke-width": 2,
                    "filled": "f"
                }, settings.gRule);
            }
        }
    }

    function _createAlarm(settings, type) {
            var alarmColor = settings.getAlarmColors();
            if (type == "create") {
                settings.gAlarm = settings.cord.createElement("g", null, settings.svg);
            } else {
                $(settings.gAlarm).empty();
            }

            var sweepRad = utils.toRad(settings.sweepAngle);

            for (var i = 0; i < settings.alarmData.length; i++) {
                var align = settings.alarmData[i] / settings.ruleMaxVal;
                var tempLine = settings.angles[0] + sweepRad * align; //算出在2pi中所占的比例
                var lineItem = _getLinePath(settings, tempLine, settings.r - settings.strokeWidth - settings.alarmCircleGap, settings.center);
                settings.cord.createElement("circle", {
                    "fill": alarmColor[i],
                    "r": 3,
                    "cx": lineItem.startX,
                    "cy": lineItem.startY,
                    "strokecolor": alarmColor[i]
                }, settings.gAlarm);
            }
        }
        //设置半径
    function _setR(settings) {
        var dia = settings.container.width() > settings.container.height() ? settings.container.height() : settings.container.width();
        settings.r = (settings.bigCirleR && settings.bigCirleR > 0) ? settings.bigCirleR : dia / 2;
        settings.r = settings.r < settings.minR ? settings.minR : settings.r;
        settings.r = settings.r > settings.maxR ? settings.maxR : settings.r;
        settings.r = settings.container.width() > settings.container.height() ? settings.r : settings.r - 30;
        var c = settings.container.width() - settings.container.height();
        settings.r = c < 50 && c > 0 ? settings.r - (50 - c) : settings.r;
        settings.strokeWidth = settings.smallCircleR >= 0 ? settings.r - settings.smallCircleR : settings.r * 1.2 - settings.r;
    }

    function _savePath(settings, type) {
        var rotate = utils.toRad(settings.rotate);
        settings.center[0] = ((settings.width) / 2) + settings.addArea / 2;
        settings.center[1] = settings.height + settings.addArea / 2;
        settings.angles.push(rotate);

        var sweepRad = utils.toRad(settings.sweepAngle);
        settings.bigAngle = sweepRad + rotate;
        var tempAngel, align = 0;
        settings.isAnimation = true;

        var align = settings.value / settings.ruleMaxVal;
        var tempAngel = settings.angles[0] + sweepRad * (align); //算出在2pi中所占的比例
        if (align == 1) {
            tempAngel -= 0.0001
        }
        settings.angles.push(tempAngel);
        if (type == "create") {
            settings.itemPath = settings.cord.createElement("path", {
                "fill": settings.baseColor,
                "stroke": settings.bgStrokeColor === undefined ? 'none' : (settings.bgStrokeColor || settings.baseColor)
            }, settings.gDashBoard);
            settings.path = settings.cord.createElement("path", {
                "fill": settings.colors,
                "stroke": settings.itemStrokeColor === undefined ? 'none' : (settings.itemStrokeColor || settings.colors)
            }, settings.gDashBoard);
        }
        if (settings.onCreateItem && typeof settings.onCreateItem == "function") {
            settings.onCreateItem(settings.path, 0);
        }

        var centerText = settings.centerText;
        var textValue = centerText.text;
        var cx = (settings.center[0]);
        var cy = (settings.center[1]);
        var fontWeight = centerText.fontWeight || "normal";
        if (!settings.text) {
            settings.text = $("<div></div>").css({
                "position": "absolute",
                "color": centerText.color
            }).appendTo(settings.cord._settings.root);
        }

        settings.text.css({
            "font-size": settings.r * settings.fontSizeRatio,
            "line-height": settings.r * settings.fontSizeRatio + "px"
        })
        if (settings.onCreateMark && typeof settings.onCreateMark == "function") {
            settings.onCreateMark(settings.text, settings.value);
        }
        //var left = (settings.root[0].scrollWidth-settings.text.width()-settings.r/2+settings.addArea)/2;
        var left = (settings.container.width() - settings.text.width()) / 2;
        var top = (settings.container.height() + settings.addArea) / 2 + settings.r/2 - settings.text.height()/2;
        settings.text.css({
            "left": left,
            "top": top
        });

        _createCir(settings, settings.data, 0, type);
        settings.self.setOnClick();
    }

    function _createCir(settings, data, index, type) {
        var tempSAngle, tempEAngle, path, flag, newAngle = 0,
            outR = settings.r,
            innerR = outR - settings.strokeWidth,
            tempIndex = 0;
        var addAngle = 0,
            animateTime = settings.animateTime / 36;

        tempSAngle = settings.angles[index];
        newAngle = tempSAngle;
        tempEAngle = settings.angles[index + 1];
        settings.cord.setAttributes(settings.path, {
            "fill": settings.colors,
            "stroke": settings.itemStrokeColor === undefined ? 'none' : (settings.itemStrokeColor || settings.colors)
        });
        flag = (settings.sweepAngle > 180) ? 1 : 0; /*大小弧度*/
        path = _getDoubleCilclePath(settings, 
            utils.toRad(settings.rotate), 
            utils.toRad((settings.rotate + settings.sweepAngle)%360), 
            innerR, outR, flag, settings.center);
        if (settings.cord.isSVG()) {
            settings.cord.setAttributes(settings.itemPath, {
                "d": path,
                "stroke": settings.bgStrokeColor === undefined ? 'none' : (settings.bgStrokeColor || settings.baseColor), 
                "stroke-width": settings.bgStrokeWidth, 
                "stroke-linejoin": settings.bgStrokeLineJoin
            });
        } else {
            settings.cord.IECom(settings, settings.itemPath, path);
        }

        if (settings.isAnimation) {
            var time = TIMERS.setInterval(function() {
                if (tempIndex != 0) {
                    addAngle = Math.PI * 2 * 1 / 36;
                }
                if (settings.lastNewAngle) {
                    if (tempEAngle > settings.lastNewAngle) {
                        settings.lastNewAngle = settings.lastNewAngle + addAngle;
                        newAngle = settings.lastNewAngle;
                        if (newAngle > tempEAngle) {
                            newAngle = tempEAngle;
                        }
                    } else {
                        settings.lastNewAngle = settings.lastNewAngle - addAngle;
                        newAngle = settings.lastNewAngle;
                        if (newAngle < tempEAngle) {
                            newAngle = tempEAngle;
                        }
                    }
                } else {
                    newAngle = newAngle + addAngle;
                    if (newAngle > tempEAngle) {
                        newAngle = tempEAngle;
                    }
                }
                if (settings.alarmData) {
                    var sweepRad = utils.toRad(settings.sweepAngle);

                    for (var i = 0; i < settings.alarmData.length; i++) {
                        var align = settings.alarmData[i] / settings.ruleMaxVal;
                        var tempLine = settings.angles[0] + sweepRad * align; //算出在2pi中所占的比例
                        if (newAngle > tempLine) {
                            settings.colors = settings.getAlarmColors()[i];
                            settings.cord.setAttributes(settings.path, {
                                "fill": settings.colors,
                                "stroke": settings.itemStrokeColor === undefined ? 'none' : (settings.itemStrokeColor || settings.colors)
                            });
                        }
                    }
                }
                flag = ((newAngle - tempSAngle) > Math.PI) ? 1 : 0; /*大小弧度*/
                path = _getDoubleCilclePath(settings, tempSAngle, newAngle, innerR, outR, flag, settings.center);
                if (settings.cord.isSVG()) {
                    settings.cord.setAttributes(settings.path, {
                        "d": path,
                        "stroke": settings.itemStrokeColor === undefined ? 'none' : (settings.itemStrokeColor || settings.colors), 
                        "stroke-width": settings.itemStrokeWidth, 
                        "stroke-linejoin": settings.itemStrokeLineJoin
                    });
                } else { //IE兼容
                    settings.cord.IECom(settings, settings.path, path);
                }
                tempIndex++;
                if (newAngle == tempEAngle) {
                    if (index + 1 <= data.length - 1) {
                        _createCir(settings, data, index + 1, type);
                    }
                    clearInterval(time);
                    settings.lastNewAngle = newAngle;
                }
            }, animateTime);
        } else {
            flag = ((tempEAngle - tempSAngle) > Math.PI) ? 1 : 0; /*大小弧度*/
            path = _getDoubleCilclePath(settings, tempSAngle, tempEAngle, innerR, outR, flag, settings.center);
            if (settings.cord.isSVG()) {
                settings.cord.setAttributes(settings.path, {
                    "d": path,
                    "stroke": settings.itemStrokeColor === undefined ? 'none' : (settings.itemStrokeColor || settings.colors), 
                    "stroke-width": settings.itemStrokeWidth, 
                    "stroke-linejoin": settings.itemStrokeLineJoin
                });
            } else {
                settings.cord.IECom(settings, settings.path, path);
            }
            if (index + 1 <= data.length - 1) {
                _createCir(settings, data, index + 1, type);
            }
        }
    }

    /*
     *算法：1、圆周长=2piR，算出当前块在2pi中所占的比例;2、x=Math.cos()*r;y=Math.sin()*r;
     */
    function _getDoubleCilclePath(settings, sdeg, edeg, rInner, rOuter, flag, center) { //获取圆环路径
        /*外弧起点坐标*/
        var startX = center[0] + Math.cos(sdeg) * rOuter;
        var startY = center[1] + Math.sin(sdeg) * rOuter;
        /*内弧起点坐标*/
        var startInnerX = center[0] + Math.cos(sdeg) * rInner;
        var startInnerY = center[1] + Math.sin(sdeg) * rInner;

        /*外弧结束坐标*/
        var endX = center[0] + Math.cos(edeg) * rOuter;
        var endY = center[1] + Math.sin(edeg) * rOuter;
        /*内弧结束坐标*/
        var endInnerX = center[0] + Math.cos(edeg) * rInner;
        var endInnerY = center[1] + Math.sin(edeg) * rInner;

        var path = "M" + startX + "," + startY + "A" + rOuter + "," + rOuter + " 0 " + flag + " 1 " + endX + "," + endY + "L" + endInnerX + "," + endInnerY + "A" + rInner + "," + rInner + " 0 " + flag + " 0 " + startInnerX + "," + startInnerY + "Z";
        return path;
    }

    function _getLinePath(settings, edeg, rOuter, center) { //获取文本线路径
        var items = {};
        /*外弧起点坐标*/
        items.startX = Math.round(center[0] + Math.cos(edeg) * (rOuter + 3));
        items.startY = Math.round(center[1] + Math.sin(edeg) * (rOuter + 3));

        /*外弧结束坐标*/
        items.endX = Math.round(center[0] + Math.cos(edeg) * (rOuter + 7));
        items.endY = Math.round(center[1] + Math.sin(edeg) * (rOuter + 7));

        items.path = "M" + items.startX + "," + items.startY + "L" + items.endX + "," + items.endY;
        return items;
    }

    /** @lends UCD.DashBoard.prototype */
    ucd.DashBoard.prototype = {
        constructor: ucd.DashBoard,
        /**
         * Initializer
         */
        init: function() {
            var settings = this._settings;
            if (!settings.data || (settings.data && !settings.data.value && settings.data.value != 0)) {
                _infoLayer(settings, "no data loaded.");
                return;
            }
            if (!settings.path) {
                _setData(settings, "create");
            } else {
                _setData(settings, "modify");
            }
        },
        /**
         * Destroy chart DOM, Events and Objects.
         */
        destroy: function() {
            var settings = this._settings;
            settings.container.empty();
            settings.cord._settings = null;
            settings.cord = null;
            settings = null;

            TIMERS.clearAll();
        },
        /**
         * set data.
         * 
         * @param {DashBoardChartData}    data         data
         * @param {Function} onCreateItem onCreateItem(path, index)
         * @param {Function} onCreateMark onCreateMark(text)
         */
        setData: function(data, onCreateItem, onCreateMark) {
            var settings = this._settings;
            if (!data || (data && !data.value && data.value != 0)) {
                return;
            }
            settings.infoLayer.hide();
            if (data.value == settings.value) {
                return;
            }
            settings.data = data;
            settings.value = data.value > settings.ruleMaxVal ? settings.ruleMaxVal : data.value;
            settings.value = data.value < 0 ? 0 : settings.value;
            settings.colors = data.color || settings.defaultColor;
            settings.onCreateItem = onCreateItem;
            settings.onCreateMark = onCreateMark;
        },
        /**
         * resize chart.
         */
        resize: function() {
            var settings = this._settings;
            if (!settings.data || (settings.data && !settings.data.value)) {
                _infoLayer(settings, "no data loaded.");
                return;
            }
            _setData(settings, "modify");
        },
        /**
         * 设置刻度
         * 
         * @param {Array}   data         data
         * @param {Number}  ruleMaxVal   刻度最大值
         * @param {Number}  ruleNum      刻度个数
         * @param {Boolean} isRule       是否显示刻度
         */
        setRule: function(data, ruleMaxVal, ruleNum, isRule) {
            var settings = this._settings;
            settings.ruleData = data;

            if (ruleMaxVal !== undefined) {
                settings.ruleMaxVal = ruleMaxVal <= 0 ? settings.ruleMaxVal : ruleMaxVal;
            }

            if (ruleNum !== undefined) {
                settings.ruleNum = ruleNum;
            }
            
            settings.isRule = isRule;
        },
        /**
         * 设置告警
         * 
         * @param {Array}  data         data
         * @param {Boolean} isShowAlarm isShowAlarm
         */
        setAlarm: function(data, isShowAlarm) {
            var settings = this._settings;
            settings.alarmData = data;
            settings.isShowAlarm = isShowAlarm == null ? settings.isShowAlarm : isShowAlarm;
        },
        /**
         * 元素click事件回调
         *
         * @event UCD.DashBoard#setOnClick
         * 
         * @param {Function} fn click(obj,index)回调事件 obj:当前对象;index:传出索引
         */
        setOnClick: function(fn) {
            var settings = this._settings;
            settings.onClick = fn ? fn : settings.onClick;
            $(settings.path).unbind(settings.Source.CLICK).bind(settings.Source, function() {
                if (settings.onClick && typeof settings.onClick == "function") {
                    settings.onClick(this, index);
                }
            });
        },
        /**
         * set radius.
         * 
         * @param {Number} bigCirleR    outer circle radius
         * @param {Number} smallCircleR inner circle radius
         */
        setR: function(bigCirleR, smallCircleR) {
            this._settings.bigCirleR = bigCirleR;
            this._settings.smallCircleR = smallCircleR;
        },
        /**
         * 选中图元
         * 
         * @param  {Number} index 索引
         */
        select: function(index) {
            var settings = this._settings;
            if (index >= 0) {
                settings.cord.setAttributes(settings.path, {
                    "fill": settings.selectColor
                });
            }
        },
        /**
         * 取消选中
         * 
         * @param  {Number} index 索引
         */
        unselect: function(index) {
            var settings = this._settings;
            if (index >= 0) {
                settings.cord.setAttributes(settings.path, {
                    "fill": settings.colors
                });
            }
        }
    }
})(UCD, UCD.Core);